home *** CD-ROM | disk | FTP | other *** search
- //---------------------------------------------------------------------------
- #include <windows.h>
- #pragma hdrstop
- #include <stdio.h>
- #include "level.h"
- //---------------------------------------------------------------------------
- //zav°enφ souboru
- int close(FILE *f,char *fn)
- {
- if(!fclose(f)) return 0;
- if( msg1(MB_ICONEXCLAMATION|MB_RETRYCANCEL,
- lng(734,"Write error, file %s"), fn) ==IDRETRY) return 2;
- return 1;
- }
- //---------------------------------------------------------------------------
- //velikost souboru
- int fsize(FILE *f)
- {
- fseek(f,0,SEEK_END);
- int len=ftell(f);
- rewind(f);
- if(len<=0){
- msg(lng(769,"Invalid file length"));
- }
- return len;
- }
- //---------------------------------------------------------------------------
- //ulo₧enφ souboru sokoban.dat
- void saveData()
- {
- start:
- if(modifData){
- FILE *f=fopen(fndata,"wb");
- if(!f){
- msg(lng(733,"Cannot write to file %d"),fndata);
- }else{
- fputs("[Sokoban Database]\r\n",f);
- for(int i=0; i<Nlevels; i++){
- Level *lev= &levoff[i];
- if(!lev->offset) continue;
- fputs(lev->offset,f);
- fputc(';',f);
- fputs(lev->author,f);
- if(lev->best.Mdata){
- fputc(';',f);
- fputs(lev->best.Mdata,f);
- }
- fputc('\r',f);
- fputc('\n',f);
- }
- int cl= close(f,fndata);
- if(cl==2) goto start;
- if(!cl) modifData=false;
- }
- }
- }
- //---------------------------------------------------------------------------
- //zm∞na hrßΦe
- void openUser()
- {
- if(!*fnuser && modifUser){
- saveUser();
- }else{
- //ulo₧enφ souΦasnΘho hrßΦe
- saveUser();
- //otev°enφ novΘho hrßΦe
- userOfn.hwndOwner= hWin;
- userOfn.Flags= OFN_PATHMUSTEXIST|OFN_HIDEREADONLY;
- for(;;){
- if(GetOpenFileName(&userOfn)){
- delUser();
- initUser();
- return; //ok
- }
- if(CommDlgExtendedError()!=FNERR_INVALIDFILENAME
- || !*userOfn.lpstrFile) return; //cancel
- *userOfn.lpstrFile=0;
- }
- }
- }
- //---------------------------------------------------------------------------
- //ulo₧enφ souboru *.rec
- void saveUser()
- {
- if(modifUser){
- if(!*fnuser){
- if(!saveFileDlg(&userOfn,true)) return;
- }
- start:
- FILE *f=fopen(fnuser,"wt");
- if(!f){
- msg(lng(733,"Cannot write to file %s"), fnuser);
- }else{
- fputs("[Sokoban Solutions]\n",f);
- for(int i=0; i<Nlevels; i++){
- Level *lev= &levoff[i];
- if(lev->user.Mdata){
- fputs(lev->user.Mdata,f);
- }
- fputc('\n',f);
- }
- int cl=close(f,fnuser);
- if(cl==2) goto start;
- if(!cl) modifUser=false;
- }
- }
- }
- //---------------------------------------------------------------------------
- //vytvo°enφ novΘ mφstnosti
- Level *addLevel()
- {
- Level *l= new Level[Nlevels+1];
- if(!l){
- msg(lng(768,"Not enough memory"));
- return 0;
- }else{
- playtime=0;
- memcpy(l,levoff,Nlevels*sizeof(Level));
- level=Nlevels;
- Nlevels++;
- delete[] levoff;
- levoff=l;
- Level *lev= l+Nlevels-1;
- lev->author="";
- lev->offset=0;
- return lev;
- }
- }
- //---------------------------------------------------------------------------
- //smazßnφ mφstnosti
- bool delLevel(int lev, HWND win)
- {
- if(lev<Nlevels && lev>=0){
- if(MessageBox(win, lng(812,"Do you really want to remove this level from database ?"),
- title, MB_YESNO|MB_ICONQUESTION|MB_DEFBUTTON2) ==IDYES){
- Level *l= new Level[Nlevels-1];
- if(!l){
- msg(lng(768,"Not enough memory"));
- }else{
- Nlevels--;
- memcpy(l, levoff, lev*sizeof(Level));
- memcpy(l+lev, levoff+lev+1, (Nlevels-lev)*sizeof(Level));
- delete[] levoff;
- levoff=l;
- modifData=modifUser=true;
- if(quickSaveLevel==lev){
- delete quickSave;
- quickSave=0;
- }
- if(quickSaveLevel>lev) quickSaveLevel--;
- playtime=0;
- if(level==lev){
- resetLevel();
- SetFocus(win);
- }
- if(level>lev) level--;
- return true;
- }
- }
- }
- return false;
- }
- //---------------------------------------------------------------------------
- //smazßnφ hracφ plochy
- void clearBoard()
- {
- Psquare dest=board;
- for(int y=0; y<height; y++){
- for(int x=0; x<width; x++){
- dest->obj= BM_GROUND;
- dest->store=false;
- if(x==1 || y==1 || x==width-2 || y==height-2) dest->obj=BM_WALL;
- if(x==0 || y==0 || x==width-1 || y==height-1) dest->obj=BM_BACKGROUND;
- dest++;
- }
- }
- }
- //---------------------------------------------------------------------------
- //zm∞na velikosti hracφ plochy
- void newBoard(int w,int h,int copy)
- {
- int moverx,movery,len,x,y;
-
- if(!w){
- RECT rcS,rcW,rcC;
- SystemParametersInfo(SPI_GETWORKAREA,0,&rcS,0);
- GetWindowRect(hWin,&rcW);
- getClient(&rcC);
- w= (rcS.right-rcS.left - rcW.right+rcW.left +
- rcC.right-rcC.left)/bmW;
- amin(w,26);
- h= (rcS.bottom-rcS.top - rcW.bottom+rcW.top +
- rcC.bottom-rcC.top)/bmH;
- amin(h,20);
- }
- if(copy==1){
- amin(w,width);
- amin(h,height);
- }
- len= w*h;
- delete[] distBuf1;
- delete[] distBuf2;
- distBuf1= new Psquare[len];
- distBuf2= new Psquare[len];
- Psquare newp= new Square[len];
- diroff[8]=0;
- diroff[3]=sizeof(Square) * w;
- diroff[2]=-diroff[3];
- diroff[1]=sizeof(Square);
- diroff[0]=-diroff[1];
- diroff[4]=diroff[0]+diroff[2];
- diroff[5]=diroff[1]+diroff[2];
- diroff[6]=diroff[0]+diroff[3];
- diroff[7]=diroff[1]+diroff[3];
-
- if(copy>=0){
- Psquare dest= newp;
- for(y=0; y<h; y++){
- for(x=0; x<w; x++){
- dest->x=x;
- dest->y=y;
- dest->distId=0;
- dest->obj= BM_GROUND;
- dest->store=false;
- if(x==0 || y==0 || x==w-1 || y==h-1) dest->obj=BM_BACKGROUND;
- dest++;
- }
- }
- }
- distId=0;
-
- if(copy==1){
- int dx= (w-width)>>1, dy= (h-height)>>1;
- for(int y=1; y<height-1; y++){
- for(int x=1; x<width-1; x++){
- Psquare src= square(x,y);
- Psquare dest= newp + x+dx + (y+dy)*w;
- if(dest->obj==BM_GROUND){
- dest->obj= src->obj;
- dest->store= src->store;
- }
- }
- }
- moverx= mover->x + dx;
- movery= mover->y + dy;
- }else{
- moverx= w>>1;
- movery= h>>1;
- }
- width=w;
- height=h;
- delete[] board;
- board= newp;
- boardk= newp+len;
- mover=square(moverx,movery);
- selected=hilited=0;
- }
- //---------------------------------------------------------------------------
- //smazßnφ nedosa₧iteln²ch polφΦek
- int optimizeLevel()
- {
- int x,y,i,d,Nobj,Nsto;
- Psquare p,pn;
-
- if(!check && notOptimize) return 0;
-
- for(p=board; p<boardk; p++) p->dist=MAXDIST;
- mover->obj= BM_GROUND;
- mover->dist=0;
- Nobj=Nsto=0;
- for(d=0; ; d++){
- bool change=false;
- for(p=board; p<boardk; p++){
- if(p->dist==d){
- if(p->obj==BM_OBJECT) Nobj++;
- if(p->store && p->obj<2) Nsto++;
- for(i=0; i<4; i++){
- pn= nxtP(p,i);
- if(pn->dist > d+1 && pn->obj<2){
- pn->dist=d+1;
- change=true;
- }
- }
- }
- }
- if(!change) break;
- }
- if(check){
- if(!Nobj){
- repaint();
- msg(lng(813,"Man cannot get to objects"));
- return 4;
- }
- if(!Nsto){
- repaint();
- msg(lng(814,"Man cannot get to targets"));
- return 5;
- }
- if(Nobj!=Nsto){
- repaint();
- msg2(lng(815,"Invalid board"),
- lng(816,"Objects: %d\r\nTargets: %d\r\n"), Nobj,Nsto);
- return 6;
- }
- }
- if(!notOptimize){
- for(p=board; p<boardk; p++){
- if(p->obj<2 && p->dist==MAXDIST){
- if(p->obj==BM_OBJECT && p->store){
- p->obj=BM_STORE;
- }else{
- p->obj=BM_WALL;
- p->store=false;
- }
- }
- }
- for(y=1; y<height-1; y++){
- for(x=1; x<width-1; x++){
- Psquare dest= square(x,y);
- for(i=0; i<9; i++){
- if(nxtP(dest,i)->obj<2) break;
- }
- if(i==9 && dest->obj==BM_WALL) dest->obj= BM_BACKGROUND;
- }
- }
- for(p=board; p<boardk; p++){
- if(p->obj==BM_STORE) p->obj=BM_OBJECT;
- }
- }
- return 0;
- }
- //---------------------------------------------------------------------------
- //vytvo°enφ zdi na okraji okna
- void fillOuter()
- {
- int x,y;
- for(y=1; y<height-1; y++){
- for(x=1; x<width-1; x++){
- Psquare dest= square(x,y);
- if(x==1 || y==1 || y==height-2 || x==width-2) dest->obj=BM_WALL;
- if(dest->obj==BM_BACKGROUND) dest->obj=BM_GROUND;
- }
- }
- }
- //---------------------------------------------------------------------------
- //spoΦte poΦet objekt∙
- int getNobj(Pchar buf)
- {
- Pchar p;
- int i=0,n;
-
- for(p=buf; *p; p++){
- n=1;
- if(*p>='A' && *p<='Z') n= *p++ -'A'+1;
- if(*p=='*' || *p=='$') i+=n;
- }
- return i;
- }
- //---------------------------------------------------------------------------
- //spoΦφtß rozm∞ry (vΦetn∞ okrajovΘ zdi)
- void getDim(Pchar buf, int &width, int &height)
- {
- int x,y,w,rep;
- Pchar p;
-
- x=y=w=0;
- for(p=buf; *p; p++){
- rep=1;
- if(*p>='A' && *p<='Z'){ rep+= *p-'A'; p++; }
- if(*p=='!'){
- amin(w,x);
- x=0;
- y++;
- }else{
- x+=rep;
- }
- }
- amin(w,x);
- if(p>buf && p[-1]!='!') y++;
- width=w+2; height=y+2;
- }
- //---------------------------------------------------------------------------
- //naΦtenφ mφstnosti z °et∞cze
- int rdLevel1(Pchar buf, int border, Level *lev)
- {
- int x,y,w;
- Pchar p;
-
- if(!buf) return 12;
- if(lev){
- w=lev->width;
- y=lev->height;
- }else{
- getDim(buf,w,y);
- }
- if(!w || !y){
- msg(lng(817,"Level is empty"));
- return 10;
- }
- if(w>127 || y>127){
- msg(lng(818,"Level is too big"));
- return 11;
- }
- border++;
- newBoard(w + 2*border-2, y + 2*border-2, (lev)? -1:0);
-
- int Nmover=0;
- bool curstore;
- char curobj;
- int n=0;
- Psquare dest=board;
- p=buf;
- for(y=0; y<height; y++){
- for(x=0; x<width; x++){
- if(dest->obj!=BM_BACKGROUND){
- if(y<border || x<border || y>=height-border || x>=width-border){
- dest->obj=BM_WALL;
- }else{
- if(!n){
- n=1;
- if(*p>='A' && *p<='Z'){
- n= *p-'A'+1;
- p++;
- }
- curstore=false;
- switch(*p++){
- case '!': case '\0':
- n=width-border-x;
- curobj= (char) (border>1 ? BM_WALL:BM_GROUND);
- break;
- case '#':
- curobj=BM_WALL;
- break;
- case '+':
- curstore=true;
- case '@':
- mover=dest;
- Nmover++;
- curobj=BM_GROUND;
- break;
- case '*':
- curstore=true;
- case '$':
- curobj=BM_OBJECT;
- break;
- case '.':
- curstore=true;
- default:
- case ' ':
- curobj=BM_GROUND;
- break;
- }
- }
- dest->obj= curobj;
- dest->store= curstore;
- n--;
- }
- }
- dest++;
- }
- if(*p=='!') p++;
- }
- if(check && Nmover!=1){
- if(!Nmover){
- msg(lng(819,"There is no man in this level"));
- return 1;
- }
- msg(lng(820,"There are %d men in this level"), Nmover);
- return 2;
- }
- return 0;
- }
- //---------------------------------------------------------------------------
- int rdLevel(Pchar buf, int border)
- {
- int e=rdLevel1(buf,border,0);
- if(e<10){
- if(!e) e=optimizeLevel();
- moverDirect=0;
- moves=pushes=0;
- undoPos=rec; redoPos=0;
- edUndo=edRec; edRedo=0;
- resize();
- status();
- }
- return e;
- }
- //---------------------------------------------------------------------------
- //p°echod do mφstnosti s Φφslem which
- int loadLevel(int which)
- {
- aminmax(which,0,Nlevels-1);
- if(replay) SendMessage(hWin,WM_COMMAND,210,0);
- if(level!=which){
- level=which;
- playtime=0;
- }
- Pchar p= levoff[which].offset;
- if(!p) return 3;
- return rdLevel(p,1);
- }
- //---------------------------------------------------------------------------
- //znovu naΦtenφ mφstnosti
- void resetLevel()
- {
- loadLevel(level);
- }
- //---------------------------------------------------------------------------
- void dels(Pchar s)
- {
- if(s && *s && (s<user || s>userk) && (s<levels || s>levelsk)){
- delete[] s;
- }
- }
- //---------------------------------------------------------------------------
- //sma₧e vÜechna u₧ivatelskß °eÜenφ z pam∞ti
- void delUser()
- {
- for(int i=0; i<Nlevels; i++){
- Solution *sol= &levoff[i].user;
- dels(sol->Mdata);
- sol->init();
- }
- delete[] user;
- user=userk=0;
- }
- //---------------------------------------------------------------------------
- //ulo₧enφ mφstnosti do °et∞zce
- Pchar wrLevel(bool pack)
- {
- int xlo,ylo,xhi,yhi,x,y,rep;
- size_t len;
- Psquare p;
- char ch,oldch;
- Pchar buf,result,s;
-
- xlo=ylo=999;
- xhi=yhi=0;
- for(p=board; p<boardk; p++){
- if(p->obj<2){
- amin(xhi,p->x);
- amin(yhi,p->y);
- amax(xlo,p->x);
- amax(ylo,p->y);
- }
- }
- if(!pack){
- xhi++; yhi++;
- xlo--; ylo--;
- }
-
- buf= new char[16384];
- if(!buf) return 0;
- s=buf;
- for(y=ylo; y<=yhi; y++){
- rep=0;
- oldch=0;
- for(x=xlo; x<=xhi; x++){
- p= square(x,y);
- if(p->store){
- if(p==mover) ch='+';
- else{
- switch(p->obj){
- case BM_GROUND:
- ch= '.';
- break;
- case BM_OBJECT:
- ch= '*';
- break;
- default:
- ch= '#';
- break;
- }
- }
- }else{
- if(p==mover) ch='@';
- else{
- switch(p->obj){
- case BM_GROUND:
- ch= ' ';
- break;
- case BM_OBJECT:
- ch= '$';
- break;
- case BM_BACKGROUND:
- if(!pack){ ch=' '; break; }
- default:
- ch= '#';
- break;
- }
- }
- }
- if(pack){
- if(ch==oldch) rep++;
- else{
- while(rep>25){
- rep-=26;
- *s++= 'Z';
- *s++= oldch;
- }
- if(rep){
- *s++= char(rep==1 ? oldch : 'A'+rep);
- rep=0;
- }
- if(oldch) *s++=oldch;
- oldch=ch;
- }
- }else{
- *s++= ch;
- }
- }
- if(pack){
- if(oldch!='#'){
- while(rep>25){
- rep-=26;
- *s++= 'Z';
- *s++= oldch;
- }
- if(rep){
- *s++= char(rep==1 ? oldch : 'A'+rep);
- }
- if(oldch) *s++=oldch;
- }
- *s++= '!';
- }else{
- s--;
- while(*s==' ') s--;
- s++;
- *s++='\n';
- }
- }
- len= s-buf;
- if(!pack) len++;
- result= new char[len];
- if(result){
- memcpy(result,buf,len);
- result[len-1]='\0';
- }
- delete[] buf;
- return result;
- }
- //---------------------------------------------------------------------------
- bool wrLevel()
- {
- Pchar result= wrLevel(true);
- if(!result) return false;
- Level *lev= &levoff[level];
- if(lev->offset && !strcmp(result,lev->offset)) return true;
- dels(lev->offset);
- lev->offset= result;
- modifData=true;
- dels(lev->best.Mdata);
- dels(lev->user.Mdata);
- lev->best.init();
- lev->user.init();
- if(quickSaveLevel==level){
- delete quickSave;
- quickSave=0;
- }
- return true;
- }
- //---------------------------------------------------------------------------
- //zjistφ, zda jsou vÜechny bedny na ·lo₧iÜtφch
- bool isFinish()
- {
- for(Psquare p=board; p<boardk; p++){
- if(p->store && p->obj==BM_GROUND) return false;
- }
- return true;
- }
- //---------------------------------------------------------------------------
- //do sol p°i°adφ °eÜenφ, ale jen pokud je lepÜφ
- void setSolution(Solution *sol, int mov, int pus, Pchar dat)
- {
- if(!mov) return;
- if(!sol->Mmoves || eval(mov,pus) < sol->eval()){
- sol->Mmoves= mov;
- sol->Mpushes= pus;
- dels(sol->Mdata);
- sol->Mdata= dat;
- }
- }
- //---------------------------------------------------------------------------
- //pokud psol je °eÜenφm mφstnosti plev, pak ho p°i°adφ do sol a vrßtφ 0
- //lev musφ mφt vypln∞nΘ rozm∞ry
- int readSolution(Pchar psol, Level *lev, Solution *sol)
- {
- int mov,pus,rep,direct,e;
- Pchar plev= lev->offset;
-
- if(!psol || isSep(*psol)) return 10;
- notMsg++;
- e=rdLevel1(plev,1,lev);
- notMsg--;
- if(e) return 4;
- mov=pus=0;
- for(Pchar p=psol; !isSep(*p); p++){
- rep=1;
- if(*p>='A' && *p<='Z'){
- rep= *p-'A'+1;
- p++;
- }
- direct= *p-'0';
- if(direct<0 || direct>7) return 11;
- while(rep--){
- mov++;
- if(direct<4){
- mover= nxtP(mover,direct);
- if(mover->obj!=BM_GROUND) return 2;
- }else{
- mover= nxtP(mover,direct-4);
- Psquare next= nxtP(mover,direct-4);
- if(mover->obj!=BM_OBJECT || next->obj!=BM_GROUND) return 3;
- next->obj= BM_OBJECT;
- mover->obj= BM_GROUND;
- pus++;
- }
- }
- }
- if(!isFinish()) return 5; //°eÜenφ je chybnΘ
- setSolution(sol,mov,pus,psol);
- return 0;
- }
- //---------------------------------------------------------------------------
- //spoΦte poΦet krok∙ a p°esun∙ v °eÜenφ psol a p°i°adφ ho do sol
- int readSolutionFast(Pchar psol, Solution *sol)
- {
- int mov,pus,rep,direct;
-
- if(!psol || isSep(*psol)) return 10;
- mov=pus=0;
- for(Pchar p=psol; !isSep(*p); p++){
- rep=1;
- if(*p>='A' && *p<='Z'){
- rep= *p-'A'+1;
- p++;
- }
- direct= *p-'0';
- if(direct<0 || direct>7) return 11;
- mov+=rep;
- if(direct>3) pus+=rep;
- }
- setSolution(sol,mov,pus,psol);
- return 0;
- }
- //---------------------------------------------------------------------------
- bool openLevel()
- {
- bool result=false;
-
- if(openFileDlg(&levelOfn)){
- FILE *f= fopen(fnlevel,"r");
- if(!f){
- msg(lng(730,"Cannot open file %s"),fnlevel);
- }else{
- int len=fsize(f);
- if(len){
- Pchar buf= new char[len];
- if(!buf){
- msg(lng(768,"Not enough memory"));
- }else{
- if(!editing){
- addLevel();
- }
- Pchar s=buf;
- int ch;
- for(;;){
- ch=fgetc(f);
- if(ch=='a' || ch=='A'){
- char author[128];
- size_t l= fread(author,1,sizeof(author)-1,f);
- author[l]='\0';
- if(!_strnicmp(author,"uthor:",6)){
- char *a= author+6;
- while(*a==' ') a++;
- char *e= strchr(a,0);
- e--;
- while(e>=a && (*e==' ' || *e=='\r' || *e=='\n')) e--;
- e++;
- *e='\0';
- l=e-a;
- if(l){
- char *&la= levoff[level].author;
- dels(la);
- la= new char[l+1];
- strcpy(la,a);
- }
- }
- }
- if(ch=='\n' || ch==EOF || ch>='A' && ch<='Z' || ch>='a' && ch<='z'){
- break;
- }
- do{
- *s++= char(ch);
- ch=fgetc(f);
- }while(ch!='\n' && ch!=EOF);
- *s++='!';
- }
- *s='\0';
- notResize++;
- int err= rdLevel(buf,0);
- notResize--;
- if(!err || err>9){
- if(editing){
- newBoard(0,0,1);
- fillOuter();
- resize();
- }else{
- notMsg++;
- optimizeLevel();
- wrLevel();
- resetLevel();
- notMsg--;
- }
- }
- delete[] buf;
- }
- }
- fclose(f);
- }
- }
- return result;
- }
- //---------------------------------------------------------------------------
- //naΦtenφ souboru sokoban.dat
- int initLevels()
- {
- int result=1;
-
- start:
- rdonly=false;
- FILE *f=fopen(fndata,"r+b");
- if(!f){
- rdonly=true;
- f=fopen(fndata,"rb");
- }
- if(!f){
- result++;
- if(result==2){
- getExeDir(fndata,"sokoban.dat");
- goto start;
- }
- if(msg1(MB_YESNO,
- lng(821,"Cannot open levels database.\r\nDo you want to find it ?")
- ) == IDYES){
- if(openFileDlg(&dataOfn)) goto start;
- }
- }else{
- int len=fsize(f);
- if(len>0){
- levels= new char[len+1];
- if(!levels){
- msg(lng(768,"Not enough memory"));
- }else{
- if(fread(levels,1,len,f)!=unsigned(len)){
- msg(lng(754,"Read error in %s"),fndata);
- }else{
- levelsk= levels+len;
- *levelsk='\n';
- Nlevels=0;
- Pchar p= levels;
- while(p<levelsk){
- Nlevels++;
- while(*p!='\n') p++;
- p++;
- }
- p=levels;
- if(*p=='['){
- while(*p!=']' && *p!='\n') p++;
- p++;
- if(*p=='\r') p++;
- if(*p=='\n') p++;
- Nlevels--;
- }
- if(Nlevels<=0){
- msg(lng(822,"Database is empty"));
- }else{
- levoff= new Level[Nlevels];
- for(int i=0; i<Nlevels; i++){
- Level *lev= &levoff[i];
- lev->author="";
- lev->offset=p;
- while(!isSep(*p)) p++;
-
- /*for(int j=0; j<i; j++){
- if(!_strnicmp(levoff[j].offset, lev->offset, p-lev->offset)){
- msg("%d = %d",i+1,j+1);
- break;
- }
- }*/
-
- if(*p==';'){
- *p++='\0';
- lev->author=p;
- while(!isSep(*p)) p++;
- while(*p==';'){
- *p++='\0';
- readSolutionFast(p, &lev->best);
- while(!isSep(*p)) p++;
- }
- }
- *p++='\0';
- if(*p=='\n') p++;
- }
- result=0;
- }
- }
- }
- }
- fclose(f);
- }
- return result;
- }
- //---------------------------------------------------------------------------
- //naΦtenφ souboru s u₧ivatelsk²m °eÜenφm
- void initUser()
- {
- int lastLev,i,Nerr=0;
- Level *lev;
-
- if(!*fnuser) return;
-
- FILE *f=fopen(fnuser,"rb");
- if(f){
- int len=fsize(f);
- if(len>0){
- user= new char[len+1];
- if(!user){
- msg(lng(768,"Not enough memory"));
- }else{
- userk= user+len;
- *userk='\n';
- if(fread(user,1,len,f)!=unsigned(len)){
- msg(lng(754,"Read error in %s"),fnuser);
- }else{
- Pchar p=user;
- if(*p=='['){
- while(*p!=']'){
- if(*p=='\n') return;
- p++;
- }
- p++;
- if(*p=='\r') p++;
- if(*p=='\n') p++;
- }
- //spoΦti velikosti vÜech level∙
- for(i=0; i<Nlevels; i++){
- lev= &levoff[i];
- getDim(lev->offset, lev->width, lev->height);
- }
- //naΦti °eÜenφ
- lastLev=0;
- while(p<userk){
- if(*p!='\r' && *p!='\n'){
- for(;;){
- if(lastLev>=Nlevels) lastLev=0;
- for(i=lastLev; ; ){
- lev= &levoff[i];
- if(!lev->user.Mmoves || i==lastLev){
- int e= readSolution(p, lev, &lev->user);
- if(!e) break;
- if(e>9){ Nerr++; break; }
- }
- i++;
- if(i>=Nlevels) i=0;
- if(i==lastLev){ Nerr++; break; }
- }
- lastLev=i;
- while(!isSep(*p)) p++;
- if(*p!=';') break;
- *p++='\0';
- }
- }
- lastLev++;
- char cr=*p;
- *p++='\0';
- if(cr=='\r' && *p=='\n') p++;
- }
- resetLevel();
- if(Nerr){
- msg(lng(823,"Failed to read %d solution%s"), Nerr, Nerr>1 ? "s":"");
- }
- setTitle(fnuser);
- }
- }
- }
- fclose(f);
- }
- for(i=0; i<Nlevels; i++){
- Level *lev= &levoff[i];
- setSolution(&lev->best,lev->user.Mmoves,lev->user.Mpushes,lev->user.Mdata);
- }
- }
- //---------------------------------------------------------------------------
- //ulo₧enφ aktußlnφ mφstnosti do souboru
- void saveLevel()
- {
- char *s = strchr(fnlevel,0);
- while(s>=fnlevel && *s!='\\') s--;
- s++;
- sprintf(s,"L%d.xsb",level+1);
- if(saveFileDlg(&levelOfn,false)){
- start:
- FILE *f= fopen(fnlevel,"wt");
- if(!f){
- msg(lng(733,"Cannot create file %s"),fnlevel);
- }else{
- if(!editing) optimizeLevel();
- Pchar buf= wrLevel(false);
- if(buf){
- fputs(buf,f);
- delete[] buf;
- }
- if(*levoff[level].author){
- fprintf(f,"Author: %s\n", levoff[level].author);
- }
- if(close(f,fnlevel)==2) goto start;
- }
- }
- }
- //---------------------------------------------------------------------------
- //provedenφ °eÜenφ bez p°ekreslovßnφ, p°i chyb∞ nastavφ movError
- void loadSolution(int lev, Pchar p)
- {
- notdraw++;
- loadLevel(lev);
- movError=0;
- int rep=1;
- while(*p && !movError){
- if(*p>='A' && *p<='Z'){
- rep= *p-'A'+1;
- p++;
- }
- if(*p>='0' && *p<='3'){
- while(rep--){
- int o=pushes,m=moves;
- moveK(*p-'0');
- if(pushes!=o || moves!=m+1) movError++;
- }
- rep=1;
- }
- if(*p>='4' && *p<='7'){
- while(rep--){
- int o=pushes;
- moveK(*p-'4');
- if(pushes!=o+1) movError++;
- }
- rep=1;
- }
- p++;
- }
- notdraw--;
- }
- //---------------------------------------------------------------------------
- //otev°enφ pozice
- void openPos()
- {
- int l;
-
- if(openFileDlg(&savOfn)){
- FILE *f= fopen(fnsave,"r");
- if(!f){
- msg(lng(730,"Cannot open file %s"),fnsave);
- }else{
- size_t len= fsize(f);
- if(len>0){
- Pchar buf= new char[len];
- if(fscanf(f," %d ",&l)!=1){
- msg(lng(824,"There is no level number"));
- }else{
- aminmax(l,1,Nlevels);
- l--;
- len= fread(buf,1,len,f);
- buf[len]='\0';
- if(!len){
- msg(lng(754,"Read error, file %s"),fnsave);
- }else{
- for(int i=l; ; ){
- notResize++;
- loadSolution(i,buf);
- notResize--;
- if(!movError){
- resize();
- update();
- break;
- }
- i--;
- if(i<0) i=Nlevels-1;
- if(i==l){
- loadLevel(l);
- msg(lng(825,"Position is wrong"));
- break;
- }
- }
- }
- }
- delete[] buf;
- }
- fclose(f);
- }
- }
- }
- //---------------------------------------------------------------------------
- //ulo₧φ °eÜenφ do °et∞zce
- Pchar wrSolution()
- {
- redoPos=0;
- undoAll();
- logPos=logbuf;
- redoAll();
- size_t len=logPos-logbuf;
- logPos=0;
- char *r = new char[len+1];
- memcpy(r,logbuf,len);
- r[len]='\0';
- return r;
- }
- //---------------------------------------------------------------------------
- //ulo₧enφ pozice
- void savePos()
- {
- if(undoPos==rec){
- msg(lng(809,"Nothing to save"));
- }else{
- if(saveFileDlg(&savOfn,false)){
- start:
- FILE *f= fopen(fnsave,"wt");
- if(!f){
- msg(lng(733,"Cannot create file %s"),fnsave);
- }else{
- fprintf(f,"%d\n",level+1);
- Pchar buf= wrSolution();
- fputs(buf,f);
- delete[] buf;
- if(close(f,fnsave)==2) goto start;
- }
- }
- }
- }
- //---------------------------------------------------------------------------
- //otestuje konec hry a p°φpadn∞ p°ejde do dalÜφ mφstnosti
- bool finish()
- {
- Pchar solution,solution2;
- Level *lev;
- Solution *sol;
- int oldM,oldP;
-
- stopTime= isFinish();
- if(!stopTime) return false;
- lev= &levoff[level];
- oldM=0;
- bool hiscore=false;
- solution=0;
- if(!rdonly){
- sol= &lev->best;
- if(!sol->Mmoves || eval(moves,pushes) < sol->eval()){
- //nejlepÜφ °eÜenφ
- if(sol->Mmoves){ oldM=sol->Mmoves; oldP=sol->Mpushes; }
- sol->Mmoves= moves;
- sol->Mpushes= pushes;
- dels(sol->Mdata);
- sol->Mdata= solution= wrSolution();
- modifData=true;
- hiscore=true;
- }
- }
- sol= &lev->user;
- if(!sol->Mmoves || eval(moves,pushes) < sol->eval()){
- //nejlepÜφ °eÜenφ tohoto hrßΦe
- if(sol->Mmoves){ oldM=sol->Mmoves; oldP=sol->Mpushes; }
- sol->Mmoves= moves;
- sol->Mpushes= pushes;
- dels(sol->Mdata);
- if(solution){
- solution2 = new char[strlen(solution)+1];
- strcpy(solution2,solution);
- sol->Mdata= solution2;
- }else{
- sol->Mdata= wrSolution();
- }
- modifUser=true;
- }
- if(oldM && gratulOn){
- msg3( MB_OK, hiscore ? lng(826,"Hiscore"):lng(827,"Congratulations !"),
- lng(828,"Previous solution: %d - %d\r\nNew solution: %d - %d\r\n"),
- oldM,oldP,moves,pushes);
- }
- return true;
- }
- //---------------------------------------------------------------------------
- //p°esun level∙
- void movLevels(Level *first, Level *last, Level *dest)
- {
- if(!first || !last || !dest) return;
- if(last<first) first=last;
- last++;
- dest++;
- size_t n= last-first;
- Level *l= new Level[n];
- memcpy(l, first, n*sizeof(Level));
- if(dest>last){
- memmove(first, last, (dest-last)*sizeof(Level));
- dest -= n;
- }else if(dest<first){
- memmove(dest+n, dest, (first-dest)*sizeof(Level));
- }
- memcpy(dest, l, n*sizeof(Level));
- delete[] l;
-
- delete quickSave;
- quickSave=0;
- modifData=true;
- }
- //---------------------------------------------------------------------------
-
-